﻿using System.Xml.Linq;
using FarseerPhysics.Dynamics;
using IcicleFramework.Components.Physics;
using Microsoft.Xna.Framework;

namespace IcicleFramework.Renderables.Components
{
    /// <summary>
    /// A renderable component that is aware of its parent's physics component and modifies
    /// its Renderable's attributes accordingly.
    /// </summary>
    public class PhysicsAwareRenderableComponent : BaseRenderableComponent, IPhysicsAwareRenderableComponent
    {
        protected string bodyName;

        protected Body body;

        protected FarseerUserData userData;

        protected IPhysicsComponent physicsComponent;

        public PhysicsAwareRenderableComponent() {}

        public PhysicsAwareRenderableComponent(PhysicsAwareRenderableComponent old)
            : base(old)
        {
            this.bodyName = old.bodyName;
            this.body = old.body;
            this.userData = old.userData;
            this.physicsComponent = old.physicsComponent;
        }

        public override void Initialize()
        {
            physicsComponent = Parent.Parent.Parent.GetComponent<IPhysicsComponent>();

            if (bodyName != string.Empty && physicsComponent != null)
                body = physicsComponent.GetBody(bodyName);

            if (body == null && physicsComponent != null)
                body = physicsComponent.GetPrimaryBody();

            if (body != null)
            {
                if (body.UserData != null)
                    userData = (FarseerUserData)body.UserData;
            }

            base.Initialize();
        }

        public override void Update(GameTime gameTime)
        {
            //Change the attributes of our parent renderable based on the given info
            //in the physics component.
            if (body != null)
            {
                Parent.Rotation = body.Rotation;
                Parent.Position = ConvertUnits.ToDisplayUnits(body.Position) + ConvertUnits.ToDisplayUnits(userData.TopLeftOffset);
            }

            base.Update(gameTime);
        }


        public override IRenderableComponent DeepClone()
        {
            return new PhysicsAwareRenderableComponent(this);
        }

        public override void Deserialize(XElement element)
        {
            bodyName = string.Empty;

            if (element.Element("body") != null)
                bodyName = element.Element("body").Value;
        }
    }
}
